#include    "aisinoexamapp.h"
#include    <stdio.h>
#include    <string>
#include    <fstream>

#define     AISINO_SAFE_DELETE(pointer)  {if(pointer){delete pointer; pointer = nullptr;}}

AisinoExamApp::AisinoExamApp(): configData(nullptr),examAnswer(nullptr),singleDB(nullptr),multipleDB(nullptr),isInit(false)
{

}

AisinoExamApp::~AisinoExamApp()
{
    AISINO_SAFE_DELETE(configData);
    AISINO_SAFE_DELETE(examAnswer);
    AISINO_SAFE_DELETE(singleDB);
    AISINO_SAFE_DELETE(multipleDB);
    isInit = false;
}

bool AisinoExamApp::init(const std::string& configFile)
{
    if(isInit)
    {
        printf("AisinoExamApp allready init!\n");
        return true;
    }
    printf("\tCopyright(C) 2018 - 2020 All Rights Reserved\n\n");

    if(configData == nullptr)
        configData = new ConfigData();

    if(configData->loadConfigFile(configFile) == false)
        return false;

    if(singleDB == nullptr)
        singleDB = new AisinoSingleDB();

    if(singleDB->loadFile(configData->getConfigValue(AISINO_SINGLE_DATABASE_FILE)) == false)
        return false;

    if(multipleDB == nullptr)
        multipleDB = new AisinoMultipleDB();

    if(multipleDB->loadFile(configData->getConfigValue(AISINO_MULTIPLE_DATABASE_FILE)) == false)
        return false;

    if(examAnswer == nullptr)
        examAnswer = new ExamAnswer();

    isInit = true;
    return true;
}

bool AisinoExamApp::analysisAisinoExamHtml()
{
    if(!isInit) {return false;}

    std::string htmlFileName = configData->getConfigValue(AISINO_EXAM_FILE);
    std::fstream htmlFile(htmlFileName,std::ios_base::in);
    if(!htmlFile.is_open())
    {
        printf("can't open %s\n",htmlFileName.c_str());
        return false;
    }

    std::string q_num_prefix    = configData->getConfigValue(AISINO_QUESTION_NUM_PREFIX);
    std::string q_num_suffix    = configData->getConfigValue(AISINO_QUESTION_NUM_SUFFIX);
    std::string q_text_begin    = configData->getConfigValue(AISINO_QUESTION_TEXT_PREFIX);
    std::string q_text_end      = configData->getConfigValue(AISINO_QUESTION_TEXT_SUFFIX);
    std::string a_text_prefix   = configData->getConfigValue(AISINO_ANSWER_TEXT_PREFIX);
    std::string a_text_suffix   = configData->getConfigValue(AISINO_ANSWER_TEXT_SUFFIX);

    bool output_file_flag       = (configData->getConfigValue(AISINO_OUTPUT_FILE_FLAG).compare("true") == 0);
    std::fstream outfile;
    if(output_file_flag)
    {
        std::string outputFileName = configData->getConfigValue(AISINO_OUTPUT_FILE_NAME);
        outfile.open(outputFileName,std::ios_base::out);
    }

    std::string text;
    bool q_text_flag = false;
    QuestionEntry question_entry;

     while(std::getline(htmlFile,text))
    {
        if(text.find(q_num_prefix) != std::string::npos )
        {
           std::string innerText = AisinoUtils::getInnerText(text,q_num_prefix,q_num_suffix);
           innerText = AisinoUtils::StringIgnoreSign(innerText);

           if(output_file_flag){ AisinoUtils::writeLine(outfile,innerText); }

           getAnswer(question_entry);
           question_entry.setQuestionNumber(innerText);
           question_entry.cleanAnswers();
        }
        else if(text.find(a_text_prefix)  != std::string::npos )
        {
           std::string innerText = AisinoUtils::getInnerText(text,a_text_prefix,a_text_suffix);
           innerText = AisinoUtils::StringIgnoreSign(innerText);

           if(output_file_flag){ AisinoUtils::writeLine(outfile,innerText); }

           question_entry.setAnswer(innerText);
        }
        else if(text.find(q_text_begin)  != std::string::npos )
        {
            q_text_flag = true;
        }
        else if(text.find(q_text_end)  != std::string::npos )
        {
            q_text_flag = false;
        }
        else if(q_text_flag)
        {
            std::string newtext = AisinoUtils::StringIgnoreSign(text);

            if(output_file_flag){ AisinoUtils::writeLine(outfile,newtext); }

            question_entry.setQuestionValue(newtext);
        }
    }

    if(output_file_flag){ outfile.close(); }

    htmlFile.close();
    return true;
}

void AisinoExamApp::getAnswer(QuestionEntry& question_entry)
{
    const std::string ANWSER[] = {"A","B","C","D","E","F","G","H"};
    unsigned int question_num = question_entry.getQuestionNumber();

    if(question_num <= 0)
    {
        return;
    }

    const std::vector<std::string> answers = question_entry.getAnswers();
    if(question_num <= 60)
    {
        for(unsigned int i = 0; i < answers.size(); i++)
        {
            if( singleDB->isQuestionAnswer(question_entry.getQuestionValue(),answers[i]) )
            {
                examAnswer->setAnswer(question_num,ANWSER[i]);
                break;
            }
        }
    }
    else
    {
        for(unsigned int i = 0; i < answers.size(); i++)
        {
            if( multipleDB->isQuestionAnswer(question_entry.getQuestionValue(),answers[i]) )
            {
                examAnswer->setAnswer(question_num,ANWSER[i]);
            }
        }
    }
}

void AisinoExamApp::showExamSolution()
{
    if(!isInit) {return;}
    examAnswer->showExamSolution();
}

